"""
Case Type   : ustore_DQL_SET_OPERATIONS
Case Name   : 场景测试—except在OALP场景测试
Create At   : 2022-05-12
Owner       : nanyang12
Description :
    1.创建表
    2.使用copy命令插入数据
    3.union在OALP场景测试
    4.环境清理
Expect      :
    1.创建成功
    2.数据插入成功
    3.成功
    4.清理成功
History     :
"""

import os
import subprocess
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro


class Ustore01(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'----- {os.path.basename(__file__)} start-----')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.pri_root = Node('PrimaryRoot')
        self.com = Common()
        self.constant = Constant()
        self.table_name1 = 't_ustore_olap_0002_01'
        self.table_name2 = 't_ustore_olap_0002_02'
        self.table_name3 = 't_ustore_olap_0002_03'
        self.table_name4 = 't_ustore_olap_0002_04'
        self.copy_file1 = 'warehouse_33.txt'
        self.copy_file2 = 'web_site_33.txt'
        self.copy_file3 = 'store_returns_33.txt'
        self.copy_file4 = 'web_page_33.txt'
        self.cur_path_1 = os.path.join(macro.SCRIPTS_PATH, self.copy_file1)
        self.cur_path_2 = os.path.join(macro.SCRIPTS_PATH, self.copy_file2)
        self.cur_path_3 = os.path.join(macro.SCRIPTS_PATH, self.copy_file3)
        self.cur_path_4 = os.path.join(macro.SCRIPTS_PATH, self.copy_file4)
        self.parent_path = os.path.dirname(macro.DB_INSTANCE_PATH)
        self.target_path1 = os.path.join(self.parent_path, self.copy_file1)
        self.target_path2 = os.path.join(self.parent_path, self.copy_file2)
        self.target_path3 = os.path.join(self.parent_path, self.copy_file3)
        self.target_path4 = os.path.join(self.parent_path, self.copy_file4)

    def test_join(self):
        step_txt = '-----step1:创建表;expect: 创建成功-----'
        self.log.info(step_txt)
        cmd_sql = f"""drop table if exists {self.table_name1}  CASCADE ;
                    drop table if exists {self.table_name2}  CASCADE ;
                    drop table if exists {self.table_name3}  CASCADE ;
                    drop table if exists {self.table_name4}  CASCADE ;
        create table {self.table_name1}
        (
            w_warehouse_sk            integer               not null,
            w_warehouse_id            char(16)              not null,
            w_warehouse_name          varchar(20)                   ,
            w_warehouse_sq_ft         integer                       ,
            w_street_number           char(10)                      ,
            w_street_name             varchar(60)                   ,
            w_street_type             char(15)                      ,
            w_suite_number            char(10)                      ,
            w_city                    varchar(60)                   ,
            w_county                  varchar(30)                   ,
            w_state                   char(2)                       ,
            w_zip                     char(10)                      ,
            w_country                 varchar(20)                   ,
            w_gmt_offset              decimal(5,2)
         ) WITH (STORAGE_TYPE=USTORE);
        create table {self.table_name2}
        (
            web_site_sk               integer               not null,
            web_site_id               char(16)              not null,
            web_rec_start_date        date                          ,
            web_rec_end_date          date                          ,
            web_name                  varchar(50)                   ,
            web_open_date_sk          integer                       ,
            web_close_date_sk         integer                       ,
            web_class                 varchar(50)                   ,
            web_manager               varchar(40)                   ,
            web_mkt_id                integer                       ,
            web_mkt_class             varchar(50)                   ,
            web_mkt_desc              varchar(100)                  ,
            web_market_manager        varchar(100)                   ,
            web_company_id            integer                  ,
            web_company_name          char(50)                      ,
            web_street_number         char(10)                      ,
            web_street_name           varchar(60)                   ,
            web_street_type           char(15)                      ,
            web_suite_number          char(50)                      ,
            web_city                  varchar(60)                   ,
            web_county                varchar(30)                   ,
            web_state                 char(20)                       ,
            web_zip                   char(50)                      ,
            web_country               varchar(20)                   ,
            web_gmt_offset            decimal(5,2)                  ,
            web_tax_percentage        decimal(5,2)                  
         )
         WITH (STORAGE_TYPE=USTORE) partition by range(web_rec_start_date)
        (
         partition p1 values less than('1990-01-01'),
         partition p2 values less than('1995-01-01'),
         partition p3 values less than('2000-01-01'),
         partition p4 values less than('2005-01-01'),
         partition p5 values less than('2010-01-01'),
         partition p6 values less than('2015-01-01'),
         partition p7 values less than(maxvalue)
        );
        create table {self.table_name3}
        (
            sr_returned_date_sk       integer                       ,
            sr_return_time_sk         integer                       ,
            sr_item_sk                integer               not null,
            sr_customer_sk            integer                       ,
            sr_cdemo_sk               integer                       ,
            sr_hdemo_sk               integer                       ,
            sr_addr_sk                integer                       ,
            sr_store_sk               integer                       ,
            sr_reason_sk              integer                       ,
            sr_ticket_number          bigint               not null,
            sr_return_quantity        integer                       ,
            sr_return_amt             decimal(7,2)                  ,
            sr_return_tax             decimal(7,2)                  ,
            sr_return_amt_inc_tax     decimal(7,2)                  ,
            sr_fee                    decimal(7,2)                  ,
            sr_return_ship_cost       decimal(7,2)                  ,
            sr_refunded_cash          decimal(7,2)                  ,
            sr_reversed_charge        decimal(7,2)                  ,
            sr_store_credit           decimal(7,2)                  ,
            sr_net_loss               decimal(7,2)                  
         )
        WITH (STORAGE_TYPE=USTORE) partition by range(sr_returned_date_sk)
        (
         partition p1 values less than (2451179) ,
         partition p2 values less than (2451544) ,
         partition p3 values less than (2451910) ,
         partition p4 values less than (2452275) ,
         partition p5 values less than (2452640) ,
         partition p6 values less than (2453005) ,
         partition p7 values less than (maxvalue)
        );
        create table {self.table_name4}
        (
            wp_web_page_sk            integer               not null,
            wp_web_page_id            char(16)              not null,
            wp_rec_start_date         date                          ,
            wp_rec_end_date           date                          ,
            wp_creation_date_sk       integer                       ,
            wp_access_date_sk         integer                       ,
            wp_autogen_flag           char(1)                       ,
            wp_customer_sk            integer                       ,
            wp_url                    varchar(100)                  ,
            wp_type                   char(50)                      ,
            wp_char_count             integer                       ,
            wp_link_count             integer                       ,
            wp_image_count            integer                       ,
            wp_max_ad_count           integer
         )
        WITH (STORAGE_TYPE=USTORE) partition by range(wp_rec_start_date)
        (
         partition p1 values less than('1990-01-01'),
         partition p2 values less than('1995-01-01'),
         partition p3 values less than('2000-01-01'),
         partition p4 values less than('2005-01-01'),
         partition p5 values less than('2010-01-01'),
         partition p6 values less than('2015-01-01'),
         partition p7 values less than(maxvalue)
        );"""
        self.log.info(cmd_sql)
        create_result = self.pri_sh.execut_db_sql(cmd_sql)
        self.log.info(create_result)
        self.assertTrue(
            create_result.count(self.constant.TABLE_CREATE_SUCCESS) == 4,
            '执行失败:' + step_txt)

        step_txt = '-----step2:使用copy命令插入数据，expect: 数据插入成功-----'
        self.log.info(step_txt)
        text = '-----step2.1: 获取当前主机的IP地址;expect: 成功-----'
        self.log.info(text)
        cmd = "ifconfig -a|grep inet6 -a2|grep broadcast|awk '{print $2}'"
        self.log.info(cmd)
        self.cur_ip = subprocess.getoutput(cmd).strip()
        self.log.info(self.cur_ip)

        text = '-----step2.2: 复制文件到数据库主机对应目录 expect: 成功-----'
        self.log.info(text)
        if self.cur_ip == self.pri_sh.node.ssh_host:
            self.log.info('当前主机是数据库主机，无需远程复制')
            cmd = f"cp {self.cur_path_1} {self.parent_path};" \
                f"cp {self.cur_path_2} {self.parent_path};" \
                f"cp {self.cur_path_3} {self.parent_path};" \
                f"cp {self.cur_path_4} {self.parent_path};"
            self.log.info(cmd)
            res = self.pri_sh.node.sh(cmd).result()
            self.log.info(res)
        else:
            self.com.scp_file(self.pri_root, self.copy_file1,
                              self.parent_path)
            self.com.scp_file(self.pri_root, self.copy_file2,
                              self.parent_path)
            self.com.scp_file(self.pri_root, self.copy_file3,
                              self.parent_path)
            self.com.scp_file(self.pri_root, self.copy_file4,
                              self.parent_path)
            chmod_cmd = f"chmod 777 -R {self.parent_path};" \
                        f"ls -al {self.parent_path}"
            self.log.info(chmod_cmd)
            chmod_result = self.pri_root.sh(chmod_cmd).result()
            self.log.info(chmod_result)

        text = '-----step2.3: 查看数据库主机目标路径下文件 expect: 成功-----'
        self.log.info(text)
        cmd = f"ls -l {self.parent_path}| grep -E '{self.copy_file1}';" \
            f"ls -l {self.parent_path}| grep -E '{self.copy_file2}';" \
            f"ls -l {self.parent_path}| grep -E '{self.copy_file3}';" \
            f"ls -l {self.parent_path}| grep -E '{self.copy_file4}';"
        self.log.info(cmd)
        res = self.pri_root.sh(cmd).result()
        self.log.info(res)
        self.assertNotIn('No such file or directory', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file1}', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file2}', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file3}', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file4}', res, '文件拷贝失败')

        text = '-----step2.4:使用copy命令插入数据，expect: 数据插入成功-----'
        self.log.info(text)
        self.log.info('---------------使用copy命令插入数据------------------')
        copy_sql = f"copy {self.table_name1} from '{self.target_path1}' " \
            f"delimiters ',';" \
            f"copy {self.table_name2} from '{self.target_path2}' " \
            f"delimiters ',';" \
            f"copy {self.table_name3} from '{self.target_path3}' " \
            f"delimiters ',';" \
            f"copy {self.table_name4} from '{self.target_path4}' " \
            f"delimiters ',';"
        self.log.info(copy_sql)
        copy_result = self.pri_sh.execut_db_sql(copy_sql)
        self.log.info(copy_result)
        self.assertIn('COPY 30', copy_result, '执行失败:' + step_txt)
        self.assertIn('COPY 2875', copy_result, '执行失败:' + step_txt)
        self.assertIn('COPY 5', copy_result, '执行失败:' + step_txt)
        self.assertIn('COPY 60', copy_result, '执行失败:' + step_txt)

        step_txt = '-----step3: union在OALP场景测试 expect: 成功-----'
        self.log.info(step_txt)
        cmd_sql = f"""
        select sr_reversed_charge,substr(sr_net_loss,1,1)::tinyint ,coalesce('',sr_return_amt,sr_store_sk,sr_return_ship_cost) 
        from {self.table_name3}
        where sr_returned_date_sk=2451179::bigint
        group by rollup(sr_reversed_charge,coalesce('',sr_return_amt,sr_store_sk,sr_return_ship_cost) ),substr(sr_net_loss,1,1)
        having coalesce('',sr_return_amt,sr_store_sk,sr_return_ship_cost) is not null
        except 
        select extract(day from wp_rec_start_date),length(wp_url),''
        from {self.table_name4}
        where exists(select 1 from {self.table_name1})
        and wp_rec_start_date < '1995-01-01'
        order by 1,2,3;
        select sr_reversed_charge,substr(sr_net_loss,1,1)::tinyint ,coalesce('',sr_return_amt,sr_store_sk,sr_return_ship_cost) 
        from {self.table_name3}
        where sr_returned_date_sk=2451179::bigint
        group by rollup(sr_reversed_charge,coalesce('',sr_return_amt,sr_store_sk,sr_return_ship_cost)),substr(sr_net_loss,1,1)
        having coalesce('',sr_return_amt,sr_store_sk,sr_return_ship_cost) is not null
        except 
        select extract(day from wp_rec_start_date)-4,length(wp_url)-12,0::tinyint
        from {self.table_name4}
        where exists(select 1 from {self.table_name1})
        and wp_rec_start_date < '2005-01-01'
        group by extract(day from wp_rec_start_date)-4,length(wp_url)-12,0
        having not exists(select web_site_sk from {self.table_name2} where web_site_sk <=-1::smallint)
        order by 1,2,3;"""
        self.log.info(cmd_sql)
        query_result = self.pri_sh.execut_db_sql(cmd_sql)
        self.log.info(query_result)
        self.assertIn('0 rows', query_result, '执行失败:' + step_txt)

    def tearDown(self):
        step_txt = '-----step4: 环境清理 expect:清理成功-----'
        self.log.info(step_txt)
        self.log.info('删除表')
        cmd_sql = self.pri_sh.execut_db_sql(f"""
                    drop table {self.table_name1} cascade;
                    drop table {self.table_name2} cascade;
                    drop table {self.table_name3} cascade;
                    drop table {self.table_name4} cascade;""")
        self.log.info(cmd_sql)
        text = '-----删除文件-----'
        self.log.info(text)
        rm_cmd = f"rm -rf {self.target_path1};" \
            f"rm -rf {self.target_path2};" \
            f"rm -rf {self.target_path3};" \
            f"rm -rf {self.target_path4};"
        self.log.info(rm_cmd)
        self.com.get_sh_result(self.pri_root, rm_cmd)
        for s in [self.target_path1, self.target_path2]:
            cmd = f'if [ -f {s} ]; then echo "does exists"; ' \
                f'else echo "not exists"; fi'
            file_judgments = self.com.get_sh_result(self.pri_root, cmd)
            self.assertIn('not exists', file_judgments, "清理失败" + text)
        self.assertTrue(
            cmd_sql.count(self.constant.DROP_TABLE_SUCCESS) == 4,
            '执行失败:' + step_txt)
        self.log.info(f'----- {os.path.basename(__file__)} end-----')
